package com.load.loaders.imp;

import japa.parser.ast.CompilationUnit;

import org.apache.log4j.Logger;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.io.SVNRepository;

import com.database.daos.IElementDao;
import com.database.objects.*;
import com.database.objects.Class;
import com.load.batch.BatchExecutor;
import com.load.loaders.ILoader;
import com.load.parsers.MethodParser;

public class LoaderClass implements ILoader {

	private static Logger logger = Logger.getLogger("load.repository");

	private IElementDao elementDao;

	private LoaderMethod loaderMethod;

	@Override
	public void loadChilds(SVNRepository svnRepository, Type type, Element<?, ?> element, BatchExecutor executor) {
		Class clazz = (Class) element;
		checkAddClass(clazz);
		checkModifyClass(svnRepository, clazz);
		checkDeleteClass(svnRepository, clazz);

		int index = 1;
		for (Method method : clazz.getChilds()) {
			elementDao.saveElement(method);
			if (clazz.getParent().isFileOO() && type.impliesLine()) {
				logger.info("METHOD: " + index + " - " + method.getLabel());
				loaderMethod.loadChilds(svnRepository, type, method, executor);
				index++;
			}
		}
	}

	private void checkAddClass(Class clazz) {
		if (clazz.isAddStatus()) {
			logger.info("CLASS: " + clazz.getName() + " - STATUS: added");

			FileOO file = clazz.getParent();
			CompilationUnit compilation = file.getCompilation();
			MethodParser.addMethods(compilation, clazz);

			logger.info("CLASS: " + clazz.getName() + " - " + clazz.getNumberChilds() + " methods");
		}
	}

	private void checkModifyClass(SVNRepository svnRepository, Class clazz) {
		if (clazz.isModifyStatus()) {
			try {
				logger.info("CLASS: " + clazz.getName() + " - STATUS: modify");

				FileOO file = clazz.getParent();
				CompilationUnit compilation = file.getCompilation();
				MethodParser.addMethods(compilation, clazz);

				Class previousClass = elementDao.getPreviousClass(clazz);
				if (previousClass != null) {
					clazz.markAddMethods(previousClass);
					clazz.markDeletedMethods(previousClass);
					clazz.markModifiedMethods(previousClass);
				} else {
					logger.warn("WARN: CLASS: " + clazz.getName() + " - doesn't previous clazz");
				}
				logger.info("CLASS: " + clazz.getName() + " - " + clazz.getNumberChilds() + " methods");
			} catch (SVNException e) {
				e.printStackTrace();
				logger.error("ERROR: marking modified methods " + clazz.getName());
			}
		}
	}

	private void checkDeleteClass(SVNRepository svnRepository, Class clazz) {
		if (clazz.isDeleteStatus()) {
			logger.info("CLASS: " + clazz.getName() + " - STATUS: delete");
			Class previousClass = elementDao.getPreviousClass(clazz);
			if (previousClass != null) {
				clazz.cloneMethods(previousClass, Status.DELETE);
			} else {
				logger.warn("WARN: CLASS: " + clazz.getName() + " - doesn't previous clazz");
			}
			logger.info("CLASS: " + clazz.getName() + " - " + clazz.getNumberChilds() + " methods");
		}
	}

	public void setElementDao(IElementDao elementDao) {
		this.elementDao = elementDao;
	}

	public void setLoaderMethod(LoaderMethod loaderMethod) {
		this.loaderMethod = loaderMethod;
	}

}